/*
 * Copyright 2002-2016 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.beans.factory.config;

import java.lang.reflect.Constructor;

import org.springframework.beans.BeansException;
import org.springframework.lang.Nullable;

/**
 * {@link InstantiationAwareBeanPostProcessor}接口的扩展，
 * 添加一个回调函数，用于预测被处理bean的最终类型。
 *
 * <p><b>注意:</b> 本接口是一个专用接口，主要用于框架内部使用。
 * 一般来说,内部后处理器应该简单地实现普通的{@link BeanPostProcessor}接口或
 * 派生自{@link InstantiationAwareBeanPostProcessorAdapter}类
 * 。即使在点发布中，也可能向该接口添加新方法。
 *
 * @author Juergen Hoeller
 * @since 2.0.3
 * @see InstantiationAwareBeanPostProcessorAdapter
 */
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {

	/**
	 * 预测最终将从中返回的bean的类型处理器的{@link #postProcessBeforeInstantiation}回调。
	 * 默认实现返回{@code null}。
	 * @param beanClass the raw class of the bean
	 * @param beanName the name of the bean
	 * @return the type of the bean, or {@code null} if not predictable
	 * @throws org.springframework.beans.BeansException in case of errors
	 */
	@Nullable
	default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
		return null;
	}

	/**
	 * 确定用于给定bean的候选构造函数。
	 * 默认实现返回{@code null}。
	 * @param beanClass the raw class of the bean (never {@code null})
	 * @param beanName the name of the bean
	 * @return the candidate constructors, or {@code null} if none specified
	 * @throws org.springframework.beans.BeansException in case of errors
	 */
	@Nullable
	default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)
			throws BeansException {

		return null;
	}

	/**
	 * 获取用于早期访问指定bean的引用，通常用于解析循环引用。
	 * 这个回调让后处理器有机会公开包装器early—即在目标bean实例完全初始化之前。
	 * 暴露的对象应该等价于what{@link #postProcessBeforeInitialization} / {@link #postProcessAfterInitialization}否则将使。
	 * 注意，此方法返回的对象将被用作bean引用，除非后处理器返回不同的包装器的后处理回调。
	 * 换句话说，就是那些后过程回调函数最终可能公开相同的引用，也可能是另一种情况从这些后续回调返回生bean实例(如果包装器
	 * 因为已经为这个方法的调用构建了受影响的bean，
	 * 默认情况下，它将作为最终bean引用公开)。
	 * 默认实现按原样返回给定的{@code bean}。
	 * @param bean the raw bean instance
	 * @param beanName the name of the bean
	 * @return the object to expose as bean reference
	 * (typically with the passed-in bean instance as default)
	 * @throws org.springframework.beans.BeansException in case of errors
	 */
	default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
		return bean;
	}

}
